package search;


import agents.Agent;
import agents.AgentState;
import agents.AutomatonAgent;
import env.Action;
import env.Enviroment;
import java.io.IOException;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;

/**
 * formally Agent2.java
 * @author orcas
 */
public class SmartAgent extends Agent {
    LinkedList<Action> plan = new LinkedList<Action>();
    private int expanded_nodes = 0;
    private NodeQueue queue;

    public SmartAgent(String name, int row, int col, NodeQueue queue) {
        super(name, row, col);
        super.setIcon(new ImageIcon("images/ShipNorth.gif"));
        this.queue=queue;
    }

    @Override
    public Action getMove() {
        if (plan == null || plan.isEmpty()) {
            rePlan();
        }
        if (plan == null || plan.isEmpty()) {
            return null;
        }
        return plan.removeFirst();
    }

    public void rePlan() {

        System.out.println("before replanning, my performance measure is " + Enviroment.f + "*" + score + " - " + expanded_nodes + " = " + ((Enviroment.f * score) - expanded_nodes));
        long start=System.currentTimeMillis();
        expanded_nodes+=graphSearch();
        long finish=System.currentTimeMillis();
        
        if (plan .isEmpty()) {
            System.out.println("i couldn't come up with a plan :(");
        } else {
            System.out.println("my new plan |" + plan.size() + "| is " + plan);
            
        }
        System.out.println("\n ----- planning time=" + (finish-start) +", total expanded_nodes="+expanded_nodes);
        //System.exit(0);
        try {
            System.out.println("press enter to confirm!");
            System.in.read();
        } catch (IOException ex) {
            Logger.getLogger(SmartAgent.class.getName()).log(Level.SEVERE, null, ex);
        }


    }

    /**********************************************************************
     **********************************************************************
     * 
     *        search-related stuff
     * 
     ***********************************************************************
     ***********************************************************************
     */
    
    public int graphSearch(){
        //glue code:
        //AgentState sentry_state = sentry.getState();//new AgentState(sentry.getRow(), sentry.getCol(), sentry.getOrientation());
        SearchState initalState = new SearchState(getState(), AutomatonAgent.getSentryState(), Enviroment.env.flags, false, isAlive());
        //Node root = new Node(null, null, 0, 0, initalState);
        Node root = new Node(null, 0, initalState);
        //PQ2 queue=new PQ2();
        plan.clear();
        HashSet<Node> closed = new HashSet<Node>();
        queue.add(root);
        closed.add(root);
        int c = 0;
        while (!queue.isEmpty()) {
            Node node = queue.poll();
            if (node.isGoal()) {
                System.out.println("@@@@ after " + c + " iteration, search has finished with " + node);
                node.getActionPath(plan);
                return c;
            }
            //System.out.println("expanding "+node);
            List<Node> expand = node.expand();
            for (Node n : expand) {
               
                if(!closed.contains(n)) {
                    queue.add(n);
                    closed.add(n);
                    //System.out.println(" + "+n);
                }
                //else System.out.println(" - "+n);
            }
            c++;
        }
        //now node is a goal node:
        System.out.println("@@@@ after " + c + " iteration, search has found no goal! @@@@");
        return c;
    }
}
